package com.fenger.billbar.demo;

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.GraphicsConfiguration;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Material;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.Timer;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;

/**
 * 自由落体
 * 
 * @author liubingzhao
 * 
 */

public class BallGravity extends Applet implements ActionListener {
	/**
	 * 
	 */
	private Button go = new Button("Go");
	// private Button stop = new Button("stop");
	private Button reset = new Button("reset");

	private float yloc = 0.5f;
	private float xloc = 0.0f;
	private float zloc = 0.0f;
	// private float sign = 1.0f; // going up or down
	private float g = 9.8f;
	private float t = 0.0f;
	private float v = 0.0f;
	private float v0 = 0.0f;// start velocity
	private float x0 = 0.0f;// start position
	private float y0 = 1.0f;// start position
	private float z0 = 0.0f;// start position
	private char  move = '+';

	private Timer timer;

	private TransformGroup objTrans;

	private Transform3D trans = new Transform3D();

	private static final long serialVersionUID = 1L;

	public BranchGroup createSceneGraph() {
		// 用来设置各种图形元素
		BranchGroup objRoot = new BranchGroup();

		// 定义一个虚拟球范围来包容所以的图形元素
		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 1000.0);
		// color background
		/*
		 * Color3f bgColor = new Color3f(1.0f,1.0f,1.0f); Background bg = new
		 * Background(bgColor); bg.setApplicationBounds(bounds);
		 * objRoot.addChild(bg); // 定义光源的类型与颜色 Color3f directionalColor = new
		 * Color3f(1.1f,1.0f,1.0f);//光源颜色 Vector3f vec = new
		 * Vector3f(0.0f,0.0f,-1.0f);//用矢量定义光源的照射方向 DirectionalLight
		 * directionalLight = new DirectionalLight(directionalColor, vec);
		 * directionalLight.setInfluencingBounds(bounds);//设置光源的作用范围
		 * objRoot.addChild(directionalLight);
		 */
		// 定义坐标变换的节点
		objTrans = new TransformGroup();
		// 允许坐标变换值能够被读写
		objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		objRoot.addChild(objTrans);

		// 定义 通过鼠标旋转对三维形体实施坐标变换的功能
		MouseRotate behavior = new MouseRotate();// 定义鼠标旋转对象
		behavior.setTransformGroup(objTrans);// 将坐标变换对象加入到鼠标旋转对象中
		objRoot.addChild(behavior);// 将旋转功能加入到根节点中
		// 设置鼠标的旋转作用范围
		behavior.setSchedulingBounds(bounds);
		// 定义鼠标的放大功能
		MouseZoom behavior2 = new MouseZoom();
		behavior2.setTransformGroup(objTrans);
		objRoot.addChild(behavior2);
		behavior2.setSchedulingBounds(bounds);

		// 定义鼠标的平移功能
		MouseTranslate behavior3 = new MouseTranslate();
		behavior3.setTransformGroup(objTrans);
		// xloc = (float) behavior3.getXFactor();
		// xloc = behavior3.
		// yloc = (float) behavior3.getYFactor();
		objRoot.addChild(behavior3);
		behavior3.setSchedulingBounds(bounds);

		// 定义物体的外观特性
		Appearance app = new Appearance();
		BufferedImage image = null;
		try {
			image = ImageIO.read(new File("D:/new_code_workspace/MyTest/src/res/ball-hdpi/ball2.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		TextureLoader texloader = new TextureLoader(image, new String("RGB"));
		app.setTexture(texloader.getTexture());
		Material material = new Material();// 表面材质
		material.setDiffuseColor(new Color3f(0.0f, 0.0f, 0.0f));// 定义散射效果
		material.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		app.setMaterial(material);// 将材质属性加入到外观对象中
		// 定义球体
		//Sphere sphere = new Sphere(0.1f, 1, 100);
		Sphere sphere = new Sphere(0.050f, -13, 100);
		sphere.setAppearance(app);
		// Box box = new Box(.5f,1.0f,1,app);
		// ColorCube ccub = new ColorCube(.5);
		objTrans.addChild(sphere);// 将球体加入到坐标对象中

		// initialize position
		// Transform3D pos1 = new Transform3D();
		trans.setTranslation(new Vector3f(x0, y0, z0));
		objTrans.setTransform(trans);

		//
		Color3f light1Color = new Color3f(1.0f, 0.0f, 0.2f);

		Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);

		DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction);

		light1.setInfluencingBounds(bounds);

		objRoot.addChild(light1);
		// 环境光
		Color3f ambientColor = new Color3f(1.0f, 1.0f, 1.0f);

		AmbientLight ambientLightNode = new AmbientLight(ambientColor);

		ambientLightNode.setInfluencingBounds(bounds);

		objRoot.addChild(ambientLightNode);

		objRoot.compile();// 对根节点进行优化预编译
		return objRoot;// 将根节点通过方法名返回
	}

	public BallGravity() {

		setLayout(new BorderLayout());// 设置有边界的显示界面
		//
		GraphicsConfiguration gc = SimpleUniverse.getPreferredConfiguration();
		// 定义显示图形的画布
		Canvas3D c = new Canvas3D(gc);
		// c.addKeyListener(this);
		// c.addMouseListener(this);
		// 定义图形在界面中的显示位置
		add("Center", c);

		timer = new Timer(10, this);

		Panel p = new Panel();

		p.add(go);
		p.add(reset);

		add("North", p);

		go.addActionListener(this);
		reset.addActionListener(this);

		// go.addKeyListener(this);

		// 通过调用方法创建包含物体、背景、坐标变换等元素的场景，
		// 并通过方法名带回一个对象赋予scene对象
		BranchGroup scene = createSceneGraph();
		//定义一个简单的虚拟空间对象
		SimpleUniverse u = new SimpleUniverse(c);
		// 在空间中自动选择合适的视点对物体进行投影
		u.getViewingPlatform().setNominalViewingTransform();

		u.addBranchGraph(scene);

		// timer.start();

	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == go) {
			if (!timer.isRunning()) {
				timer.start();
			}
		}

		if (e.getSource() == reset) {
			xloc = x0;
			yloc = y0;
			zloc = z0;
			t = 0.0f;
			v0 = 0.0f;
			timer.stop();

			trans.setTranslation(new Vector3f(xloc, yloc, zloc));
			objTrans.setTransform(trans);
		}

		t += 0.01f;// 每次调用时间增加0.1s
		v = v - g * 0.01f;
		yloc = yloc + v * 0.01f;
		if (yloc < 0.0f) {
			v = -0.8f * v;
			yloc = 0.0f;
			// t = 0.0f;
			// y0 = -0.5f;
		}
		trans.setTranslation(new Vector3f(xloc, yloc, zloc));
		/*
		 * 平移旋转
		 */
		if(yloc == 0.0){
			//当小球落地时开始沿x平移0.8m
			Transform3D rot1 = new Transform3D();
			if(xloc < -0.8){
				move = '+';
				//xloc= xloc+ 0.001f;
				//double r = Math.sqrt(x*x+y*y+z*z);
				//double alpha1 = Math.atan(x/z);	
				//double alpha2 = Math.acos(y/r);	
				//rot1.setTranslation(new Vector3f(xloc, yloc, zloc));
				//rot1.rotX(t*.01);	// 绕Y旋转α1度
				//rot2.rotZ(-t*.01);	// 绕X旋转α2度
				//Transform3D newTransform = new Transform3D();
				System.out.println("action:[move"+move+"]x:"+xloc+" y:"+yloc+" z:"+zloc+" t:"+t+" v:"+v);
			}
			if(xloc > 0.8){
				move = '-';
				System.out.println("action:[move"+move+"]x:"+xloc+" y:"+yloc+" z:"+zloc+" t:"+t+" v:"+v);
			}
			if(xloc < -0.8 && move == '+'){
				move = 'm';
			}
			switch (move) {
				case '-'://沿x负向滚动（平移和旋转）
					xloc= xloc - 0.005f;
					rot1.rotZ(0.2);
					break;
				case '+'://沿x正向滚动（平移和旋转）
					xloc= xloc + 0.005f;
					rot1.rotZ(-0.2);
					break;
				case 'm'://沿x,y等速正向滚动（平移和旋转）
					xloc += 0.005f;
					yloc += 0.005f;
					rot1.rotZ(-0.2);
					break;
				default:
					break;
			}
			// 叠加两次旋转的效果
			trans.mul(rot1);
		}
		objTrans.setTransform(trans);

	}

	public static void main(String[] args) {
		System.out.println("Program Started");
		BallGravity bb = new BallGravity();
		// bb.addKeyListener(bb);
		new MainFrame(bb, 600, 600);

	}

}
